package com.jichangxiu.common.entity.vo;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.jichangxiu.common.constant.Constants;
import com.jichangxiu.common.entity.bo.Record;
import com.jichangxiu.common.enums.ErrorType;
import com.jichangxiu.common.utils.ObjUtils;

import java.io.Serializable;
import java.util.List;

public class Result<T> extends Record implements Serializable {

    private static final long serialVersionUID = 1L;

    private Result() {
    }

    public static <T> Result<T> ok(String message, T data) {
        Result<T> result = new Result<>();
        result.set(Constants.TO_CLIENT_STATUS_KEY, Constants.CLIENT_STATUS_SUCCESS_VALUE);
        result.set(Constants.TO_CLIENT_CODE_KEY, Constants.CLIENT_CODE_SUCCESS_VALUE);
        result.set(Constants.TO_CLIENT_MESSAGE_KEY, message);
        result.set(Constants.TO_CLIENT_DATA_KEY, data);
        return result;
    }

    public static <T> Result<T> ok(T data) {
        return ok(Constants.CLIENT_MESSAGE_SUCCESS_VALUE, data);
    }

    public static <T> Result<T> ok(String message) {
        return ok(message, null);
    }

    public static <T> Result<T> ok() {
        return ok(Constants.CLIENT_MESSAGE_SUCCESS_VALUE);
    }

    public static <T> Result<T> no(Integer code, String message) {
        Result<T> result = new Result<>();
        result.set(Constants.TO_CLIENT_STATUS_KEY, Constants.CLIENT_STATUS_FAIL_VALUE);
        result.set(Constants.TO_CLIENT_CODE_KEY, code);
        result.set(Constants.TO_CLIENT_MESSAGE_KEY, message);
        result.set(Constants.TO_CLIENT_DATA_KEY, null);
        return result;
    }

    public static <T> Result<T> no(String message) {
        return no(Constants.CLIENT_CODE_FAIL_VALUE, message);
    }

    public static <T> Result<T> no() {
        return no(Constants.CLIENT_CODE_FAIL_VALUE, Constants.CLIENT_MESSAGE_FAIL_VALUE);
    }

    public static <T> Result<T> no(ErrorType errorType) {
        return no(errorType.getCode(), errorType.getMessage());
    }

    public static <T> Result<T> no(Exception exception) {
        return no(Constants.CLIENT_CODE_FAIL_VALUE, exception.getMessage());
    }

    public Result<T> STATUS(Boolean status) {
        this.set(Constants.TO_CLIENT_STATUS_KEY, status);
        return this;
    }

    public Result<T> CODE(Integer code) {
        this.set(Constants.TO_CLIENT_CODE_KEY, code);
        return this;
    }

    public Result<T> MESSAGE(String message) {
        this.set(Constants.TO_CLIENT_MESSAGE_KEY, message);
        return this;
    }

    public Result<T> DATA(T data) {
        this.set(Constants.TO_CLIENT_DATA_KEY, data);
        return this;
    }

    public static Object toResult(Object body) {
        try {
            // 如果对象是空的，则返回成功提示
            if (ObjectUtil.isEmpty(body))
                return JSONUtil.parseObj(Result.ok());

            // 如果对象是 String 则需要将返回内容放入 msg 中一份
            if (body instanceof String) {
                String str = String.valueOf(body);
                if (StrUtil.isNotEmpty(str)) {
                    // 去除字符串前后双引号
                    str = str.startsWith("\"") ? str.substring(1) : str;
                    str = str.endsWith("\"") ? str.substring(0, str.length() - 1) : str;
                }
                return JSONUtil.parseObj(Result.ok(Constants.CLIENT_MESSAGE_SUCCESS_VALUE, str));
            }

            // 如果是 List 对象
            if (body instanceof List<?>) {
                // 处理时间
                List<?> objectList = (List<?>) body;
                if (ObjectUtil.isEmpty(objectList))
                    return JSONUtil.parseObj(Result.ok(body));
                else if (objectList.get(0) instanceof String)
                    return JSONUtil.parseObj(Result.ok(body));
                else {
                    List<Record> recordList = Record.getRecordByList(objectList);
                    ObjUtils.formatObject(recordList);
                    return JSONUtil.parseObj(Result.ok(recordList));
                }
            }

            // 如果是分页数据
            if (body instanceof PageResult) {
                PageResult pageResult = (PageResult) body;
                ObjUtils.formatObject(Record.getRecordByList(pageResult.getList()));
                return JSONUtil.parseObj(Result.ok(pageResult));
            }

            // 如果就是 Result 对象直接返回
            if (body instanceof Result) {
                // 处理时间
                Record model = Record.getRecordByModel(body);
                ObjUtils.formatObject(model.getModel(Constants.TO_CLIENT_DATA_KEY, Record.class));
                return JSONUtil.parseObj(model);
            }

            // 防止 object instanceof Result 没有被识别
            Record record = Record.getRecordByModel(body);
            if (StrUtil.isNotEmpty(record.getStr(Constants.TO_CLIENT_STATUS_KEY))
                    && StrUtil.isNotEmpty(record.getStr(Constants.TO_CLIENT_CODE_KEY))
                    && StrUtil.isNotEmpty(record.getStr(Constants.TO_CLIENT_MESSAGE_KEY))) {
                // 处理时间
                ObjUtils.formatObject(record.getModel(Constants.TO_CLIENT_DATA_KEY, Record.class));
                return JSONUtil.parseObj(record);
            }

            // 防止 Record.getRecordByModel(object) 没有被识别
            String json = JSONUtil.toJsonStr(body);
            if (JSONUtil.isTypeJSONObject(json)) {
                JSONObject jsonObject = JSONUtil.parseObj(json);
                // 如果本来就是 Result 对象，则不需要在进行包装，直接返回。
                if (StrUtil.isNotEmpty(jsonObject.getStr(Constants.TO_CLIENT_STATUS_KEY))
                        && StrUtil.isNotEmpty(jsonObject.getStr(Constants.TO_CLIENT_CODE_KEY))
                        && StrUtil.isNotEmpty(jsonObject.getStr(Constants.TO_CLIENT_MESSAGE_KEY))) {
                    // 处理时间
                    Record data = Record.getRecordByModel(jsonObject.getJSONObject(Constants.TO_CLIENT_DATA_KEY));
                    ObjUtils.formatObject(data);
                    jsonObject.set("data", data);
                    return jsonObject;
                }
            }

            // 处理时间
            // 其余返回
            Record model = Record.getRecordByModel(body);
            ObjUtils.formatObject(model);
            return JSONUtil.parseObj(Result.ok(model));
        } catch (Exception ex) {
            // JSON 转换失败
            throw new RuntimeException("【Result】统一返回值封装异常", ex);
        }
    }

}
